<template>
	<div class="flv-Video">
		<iframe
			v-if="state.isIframe"
			:src="`${state.origin}/wasmPlayer/sansan-player.html?videoUrl=${videoUrl}`"
			frameborder="0"
			class="w-full h-full"
		></iframe>
		<div v-else>
			<video
				v-if="!player"
				style="width: 100%; height: 100%"
				:class="state.isMp4 ? 'mp4-video' : 'real-video'"
				:poster="poster"
				preload="auto"
			></video>
			<video
				v-show="player"
				ref="screenVideo"
				controls
				x5-video-player-type="h5"
				muted
				style="width: 100%; height: 100%"
				:poster="poster"
				preload="auto"
			></video>
			<div class="mask"></div>
			<span v-if="error" class="error">{{ error }}</span>
			<div v-show="player" v-if="!props.noClose" class="close" @click="closeVideo">关闭</div>
		</div>
	</div>
</template>

<script setup lang="ts" name="videoBox">
import poster from "@public/images/decoration/video.png";
import mpegts from "mpegts.js";
import { ref } from "vue";
import { useAttrs } from "element-plus";
const emit = defineEmits(["close"]);
const props = defineProps({
	noClose: {
		type: Boolean,
		default() {
			return false;
		}
	}
});
const state = reactive({
	isIframe: false,
	isMp4: false,
	origin: window.location.origin
});
const screenVideo = ref(null);
let player = ref<any>(null);
let timerIndex = ref<number>(0);
const lastDecodedFrame = ref<any>(0);
const intervalId = ref<any>(null);
const videoUrl = ref<string>("");
const error = ref();
const playVideo = async (url: string) => {
	error.value = "";
	state.isMp4 = url.endsWith(".mp4");
	closeVideo();
	if (videoUrl.value != url) {
		videoUrl.value = url;
	}
	console.log("video url=" + videoUrl.value);
	if (!videoUrl.value) {
		console.warn("no video url.");
		return;
	}
	if (mpegts.getFeatureList().mseLivePlayback) {
		player.value = mpegts.createPlayer(
			{
				type: "flv", // could also be mpegts, m2ts, flv
				isLive: true,
				url: videoUrl.value
			},
			{
				autoCleanupSourceBuffer: true, //对SourceBuffer进行自动清理
				autoCleanupMaxBackwardDuration: 30, //    当向后缓冲区持续时间超过此值（以秒为单位）时，请对SourceBuffer进行自动清理
				autoCleanupMinBackwardDuration: 8, //指示进行自动清除时为反向缓冲区保留的持续时间（以秒为单位）。
				enableStashBuffer: false, //关闭IO隐藏缓冲区
				isLive: true,
				lazyLoad: false
			}
		);
		player.value.attachMediaElement(screenVideo.value);
		player.value.load();
		player.value.play();

		// 【mpegts播放器事件侦听】
		player.value.on(mpegts.Events.LOADING_COMPLETE, (res: any) => {
			console.log(res);
			console.log("加载完成");
		});
		player.value.on(mpegts.Events.MEDIA_INFO, (res: any) => {
			console.log(res);
			console.log("媒体信息");
		});
		player.value.on(mpegts.Events.METADATA_ARRIVED, (res: any) => {
			console.log(res);
			console.log("获取元数据");
		});
		player.value.on(mpegts.Events.RECOVERED_EARLY_EOF, (res: any) => {
			console.log(res);
			console.log("恢复早期EOF");
		});
		player.value.on(mpegts.Events.SCRIPTDATA_ARRIVED, (res: any) => {
			console.log(res);
			console.log("获取到脚本数据");
		});

		//画面卡死
		player.value.on(mpegts.Events.STATISTICS_INFO, (res: any) => {
			if (lastDecodedFrame.value == 0) {
				lastDecodedFrame.value = res.decodedFrames;
				timerIndex.value = 0;
				return;
			}
			if (lastDecodedFrame.value != res.decodedFrames) {
				lastDecodedFrame.value = res.decodedFrames;
				timerIndex.value = 0;
			} else {
				if (timerIndex.value >= 10) {
					timerIndex.value = 0;
					lastDecodedFrame.value = 0;
					if (player.value) {
						closeVideo();
						playVideo(videoUrl.value);
					}
				} else {
					timerIndex.value = timerIndex.value + 1;
				}
			}
		});

		//断流重连
		player.value.on(mpegts.Events.ERROR, (errorType: any, errorDetail: any, errorInfo: any) => {
			console.log("视频错误信息回调");
			console.log("errorType:", errorType);
			console.log("errorDetail:", errorDetail);
			console.log("errorInfo:", errorInfo);
			if (errorInfo?.code == 502) {
				error.value = "视频服务异常";
				closeVideo();
				return;
			} else if (errorInfo?.code == 404) {
				error.value = "视频地址错误";
				closeVideo();
				return;
			} else if (errorInfo?.code == -1) {
				error.value = errorInfo?.msg;
				closeVideo();
				return;
			} else if (errorInfo?.msg?.includes(") is unsupported.")) {
				closeVideo();
				error.value = "当前环境不支持该视频编码格式";
				state.isIframe = true;
			} else {
				playVideo(url);
			}
		});
	}
};

onMounted(() => {
	let attrs = useAttrs();
	playVideo(attrs.value.videoUrl as string);
	intervalId.value = window.setInterval(() => {
		if (!player.value) return;
		if (player.value.buffered.length) {
			let end = player.value.buffered.end(0); //获取当前buffered值
			let diff = end - player.value.currentTime; //获取buffered与currentTime的差值
			if (diff >= 4) {
				console.log("处理延迟");
				//如果差值大于等于0.5 手动跳帧 这里可根据自身需求来定
				player.value.currentTime = player.value.buffered.end(0) - 1.5; //手动跳帧
			}
		}
	}, 2000); //2000毫秒执行一次
});

onBeforeUnmount(() => {
	closeVideo();
	clearInterval(intervalId.value);
	intervalId.value = null;
});

const closeVideo = () => {
	if (player.value) {
		player.value.pause();
		player.value.unload();
		player.value.detachMediaElement();
		player.value.destroy();
		player.value = null;
	}
	emit("close");
};

defineExpose({
	playVideo,
	closeVideo
});
</script>

<style lang="scss" scoped>
.flv-Video {
	position: relative;
	display: flex;
	width: 100%;
	height: 100%;
	video {
		width: 100%;
		height: 100%;
		background-color: #000000;
	}
	.mask {
		position: absolute;
		top: 0;
		right: 0;
		bottom: 60px;
		left: 0;
		z-index: 10;
		opacity: 0;
	}
	.error {
		position: absolute;
		top: 30%;
		left: 50%;
		color: #aaaaaa;
		transform: translate(-50%, -50%);
	}
	.close {
		position: absolute;
		top: 5px;
		right: 5px;
		z-index: 12;
		max-width: 120px;
		padding: 2px 5px;
		overflow: hidden;
		font-size: 12px;
		color: #ffffff;
		text-overflow: ellipsis;
		white-space: nowrap;
		cursor: pointer;
		background-color: hsl(0deg 0% 50% / 50%);
		border-radius: 2px;
	}
}
</style>
